#include "multiplayer.h"
#include "ui_multiplayer.h"
#include <QPushButton>
#include <QHostAddress>
#include <QByteArray>
#include <QString>
#include <string.h>
#include <QDebug>
#include <QPainter>

// 构造函数
MultiPlayer::MultiPlayer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MultiPlayer)
{
    ui->setupUi(this);

    // 窗口基本属性设定
    this->setWindowTitle("五子棋-联机");
    this->setFixedSize(900, 600);
    ui->btn_restart->setEnabled(false); // 默认状态下重开按钮不可用
    ui->btn_sendMsg->setEnabled(false); // 在连接成功之前发送按钮不可用

    // 成员数据初始化
    my_chess = BLACK;                   // 默认棋子为黑子 当收到服务器要求改变棋子类型时 修改
    chessBoard = new ChessBoard(this);  // 创建棋盘
    chessBoard->move(40, 20);
    m_tcp = new QTcpSocket(this);       // 客户端套接字初始化

    // 按钮功能设定
    connect(ui->btn_back, &QPushButton::clicked, this, &MultiPlayer::btn_back); // 返回主界面
    connect(ui->btn_quit, &QPushButton::clicked, this, &MultiPlayer::btn_quit); // 退出游戏
    connect(ui->btn_restart, &QPushButton::clicked, this, &MultiPlayer::btn_restart);   // 重新开始
    connect(ui->btn_sendMsg, &QPushButton::clicked, this, &MultiPlayer::btn_send);      // 发送信息

    // 己方落子
    connect(chessBoard, &ChessBoard::pos_press, this, &MultiPlayer::set_chess);

    // 套接字信号绑定
    connect(m_tcp, &QTcpSocket::connected, this, &MultiPlayer::connected);          // 连接成功检测
    connect(m_tcp, &QTcpSocket::readyRead, this, &MultiPlayer::recv_msg);           // 接收消息
    connect(m_tcp, &QTcpSocket::disconnected, this, &MultiPlayer::disconnected);    // 断开连接检测
}

// 析构函数
MultiPlayer::~MultiPlayer()
{
    delete ui;
    m_tcp->close();
    delete m_tcp;
    delete chessBoard;
}

// 设置窗口背景 绘图事件
void MultiPlayer::paintEvent(QPaintEvent *ev)
{
    // 定义画家 作画位置为this
    QPainter* painter = new QPainter(this);

    // 设置绘画内容
    QPixmap pix;
    pix.load(":/res/background.jpg");
    pix.scaled(this->width(), this->height());

    // 画家在指定位置 将预设内容画出来
    painter->drawPixmap(0, 0, this->width(), this->height(), pix);
    delete painter;
}

// 槽函数 开始建立连接
void MultiPlayer::create_client()
{
    // 连接服务器
    ui->chatBox->append("[系统提示]正在连接服务器，请稍后...");
    m_tcp->connectToHost(QHostAddress(""), 8000);
}

// 槽函数 接收来自服务器的消息
void MultiPlayer::recv_msg()
{
    // 读取来自服务器的全部数据
    QByteArray msg = m_tcp->readAll();

    // 分析数据内容
    char* str = msg.data();
    if(strncmp(str, "TYPE", 4) == 0)       // 设置棋子类型为白子信息
    {
        sscanf(str, "TYPE(%d)", &my_chess); // 提取服务器分配的棋子类型
        chessBoard->setGame_start(true);    // 设置游戏状态为开始
        ui->chatBox->append("[系统提示]游戏开始咯，本游戏谁手快谁先手");
    }
    else if(strncmp(str, "POS", 3) == 0)     // 收到落子位置信息 格式POS(5,5)CHESS(-1)
    {
        int row, col, chess_type;
        sscanf(str, "POS(%d,%d)CHESS(%d)", &row, &col, &chess_type);
        if(chess_type == my_chess)
        {
            my_chess = -chess_type;     // 以防万一双方棋子类型冲突
        }

        // 根据读取到的对方落子位置 设置棋盘
        bool game_start = chessBoard->set_chess(row, col, chess_type);
        if(!game_start)
        {
            ui->chatBox->append("[系统提示]很遗憾，本局你输了，请点击重新开始按钮再来一局吧"); // 输掉了
            // 设置重开按钮可用
            ui->btn_restart->setEnabled(true);
        }
    }
    else if(strncmp(str, "RESTART", 7) == 0) // 收到重开信息
    {
        // 禁用重开按钮
        ui->btn_restart->setEnabled(false);
        // 打印提示信息
        ui->chatBox->append("[系统提示]对方还想再来一局，并选择了重新开始");
        // 重置棋盘
        chessBoard->reset_board();
    }
    else if(strncmp(str, "CLOSE", 5) == 0)  // 收到对方已退出信息
    {
        // 打印提示信息
        ui->chatBox->append("[系统提示]小伙伴离开了，正在返回主界面");
        ui->chatBox->setText("");   // 清空聊天栏
        ui->input_msg->setText(""); // 清空输入框
        chessBoard->reset_board();  // 重置棋盘
        m_tcp->close();             // 关闭套接字
        emit back();                // 反回主界面
    }
    else if(strlen(str) > 0)    // 收到聊天信息 直接显示在聊天栏
    {
        QString chat_msg = "[小伙伴]";
        chat_msg += str;
        ui->chatBox->append(chat_msg);
    }
}

// 槽函数 在点击位置落子 并发送位置和棋子类型信息给服务器
void MultiPlayer::set_chess(int arg[])
{
    // 在棋盘中落子 并判断是否分出胜负
    bool game_start = chessBoard->set_chess(arg[0], arg[1], my_chess);

    // 将落子位置 和 棋子类型信息发送给服务器
    // 组包
    QByteArray msg;
    msg.append("POS(");
    msg.append(QString::number(arg[0]));
    msg.append(",");
    msg.append(QString::number(arg[1]));
    msg.append(")CHESS(");
    msg.append(QString::number(my_chess));
    msg.append(")");
    // 发送
    m_tcp->write(msg);

    // 判断游戏是否结束
    if(!game_start)
    {
        ui->chatBox->append("[系统提示]恭喜你，你赢了，请点击重新开始按钮再来一局吧"); // 已胜利

        // 设置重开按钮可用
        ui->btn_restart->setEnabled(true);
    }
}

// 槽函数 与服务器连接成功
void MultiPlayer::connected()
{
    // 连接成功后 第一时间先显示提示信息
    ui->chatBox->append("[系统提示]成功加入房间 请等待游戏开始..");
    // 设置发送按钮可用
    ui->btn_sendMsg->setEnabled(true);
}

// 槽函数 服务器已断开连接
void MultiPlayer::disconnected()
{
    ui->chatBox->append("[系统提示]服务器已经断开连接，即将回到主界面...");    
    emit back();
}

// 槽函数 重新开始按钮
void MultiPlayer::btn_restart()
{
    chessBoard->reset_board();
    ui->chatBox->append("[系统提示]棋盘已重置，开始新的一局吧");

    // 通知对方也重开
    QByteArray msg;
    msg.append("RESTART");
    m_tcp->write(msg);

    // 禁用重开按钮
    ui->btn_restart->setEnabled(false);
}

// 槽函数 退出游戏按钮
void MultiPlayer::btn_quit()
{    
    emit quit();
}

// 槽函数 退回主界面按钮
void MultiPlayer::btn_back()
{
    ui->chatBox->setText("");   // 清空聊天记录
    ui->input_msg->setText(""); // 清空输入框
    chessBoard->reset_board();  // 重置棋盘
    m_tcp->close();     // 关闭套接字
    emit back();
}

// 槽函数 发送信息按钮
void MultiPlayer::btn_send()
{
    // 获取到输入的内容
    QString msg = ui->input_msg->toPlainText();
    if(msg == "")
    {
        return;
    }

    // 清空输入框
    ui->input_msg->setText("");

    // 发送
    m_tcp->write(msg.toUtf8());

    // 显示到自己的聊天栏
    QString str = "[你自己]";
    str += msg;
    ui->chatBox->append(str);
}


